// copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
// see COPYRIGHT for reuse legalities
//


#import "WW3DShapeControlPanel.h"
#import "WW3DShape.h"
#import "PAThumbWheel.h"

@implementation WW3DShapeControlPanel

- init
{
   [super init];

   absoluteTransforms = 0;
   preConcat = 1;
   xRotateOrTranslate = 0;
   yRotateOrTranslate = 0;
   zRotateOrTranslate = 0;

   return self;
}


- free
{
  if (matricesPanel)
  {  [matricesPanel free];
  }
  if (transformPanel)
  {  [transformPanel free];
  }
  if (ribPanel)
  {  [ribPanel free];
  }
  if (shadingPanel)
  {  [shadingPanel free];
  }
  if (theControlPanel)
  {  [theControlPanel close];
  }
  return [super free];
}


- setShape:newShape  { shape = newShape;   return self; }

- showControlPanel:sender
{
  if (!theControlPanel)
  {  id     bundle = [NXBundle bundleForClass: [self class]];
     char   path[MAXPATHLEN + 1];

     if (!bundle) 
     {  NXLogError("No bundle for Class %s - unable to showControlPanel\n", [self name]);
        return nil;
     }
     if (![bundle getPath:path forResource:"WW3DShapeControlPanel" ofType:"nib"])
     {  NXLogError("No path for WW3DShapeControlPanel.nib.\n");
        return nil;
     }
     [NXApp loadNibFile:path owner:self  withNames:NO fromZone:[self zone]];
     //NXLogError ("Loaded %s.\n", path);
  }
  [self revert:nil];
  [theControlPanel display];
  [theControlPanel makeKeyAndOrderFront:sender];
  return self;
}

- drawRtMatrix:(RtMatrix)anRtMatrix inMatrix:aMatrix
{
  int  i, j;


  for (i = 0; i < 4; i++)
  {  for (j = 0; j < 4; j++)
     {  [[aMatrix cellAt:i :j] setFloatValue:anRtMatrix[i][j]];
     }
  }
  return self;
}

- fillRIBCommandsMatrix:theMatrix
{
   int  howMany, i;
   id   newCell;


   howMany = [[theMatrix cellList] count];
   for (i = 0; i < howMany; i++)
   {  [theMatrix removeRowAt:0 andFree:YES];
      [theMatrix sizeToCells];
   }
   howMany = [[shape ribCommands] count];
   for (i = 0; i < howMany; i++)
   {  [theMatrix addRow];
      [theMatrix sizeToCells];
      newCell = [theMatrix cellAt:i :0];
//Note: these really should be double-clickable themselves...
      [newCell setStringValue:[[[[shape ribCommands] objectAt:i] class] name]];
   }

   return self;
}


- revert:sender
{
   RtMatrix  anRtMatrix;
   RtBound   boundingBox;


   [relativeAbsoluteButtons selectCellWithTag:absoluteTransforms];
   [prePostButtons selectCellWithTag:preConcat];

   [shapeName setStringValue:[shape shapeName]];

   [(WW3DShape *)shape getBoundingBox:&boundingBox];
   [[boundingBoxMatrix cellAt:0 :0] setFloatValue:boundingBox[0]];
   [[boundingBoxMatrix cellAt:1 :0] setFloatValue:boundingBox[1]];
   [[boundingBoxMatrix cellAt:0 :1] setFloatValue:boundingBox[2]];
   [[boundingBoxMatrix cellAt:1 :1] setFloatValue:boundingBox[3]];
   [[boundingBoxMatrix cellAt:0 :2] setFloatValue:boundingBox[4]];
   [[boundingBoxMatrix cellAt:1 :2] setFloatValue:boundingBox[5]];

   [shape getInitialTransformMatrix:anRtMatrix];
   [self drawRtMatrix:anRtMatrix inMatrix:initialTransformMatrix];
   [shape getTransformMatrix:anRtMatrix];
   [self drawRtMatrix:anRtMatrix inMatrix:transformMatrix];
   [shape getCompositeTransformMatrix:anRtMatrix relativeToAncestor:[shape ancestor]];
   [self drawRtMatrix:anRtMatrix inMatrix:compositeTransformMatrix];

   [self fillRIBCommandsMatrix:ribCommandsMatrix];

   return self;
}


- setTransformMatrix_:sender
{
   int  i, j;


   for (i = 0; i < 4; i++)
   {  for (j = 0; j < 4; j++)
      {  tmpMatrix[i][j] = [[sender cellAt:i :j] floatValue];
      }
   }
   [shape setTransformMatrix:tmpMatrix];

   return self;
}

- firmCTM:sender
{
    return self;
}

- hardenPoints:sender
{
    return self;
}

- setCompositeTransformMatrix_:sender
{
    return self;
}

- setInitialTransformMatrix_:sender
{
    return self;
}

- setRelativeOrAbsolute_:sender
{
  absoluteTransforms = [[sender selectedCell] tag];
  return self;
}

- setPreOrPost_:sender
{
  preConcat = [[sender selectedCell] tag];
  return self;
}

- setXConstrained_:sender
{
    return self;
}

- setXMax_:sender
{
    return self;
}

- setXMin_:sender
{
    return self;
}

- setXRotateOrTranslate_:sender
{
   xRotateOrTranslate = [[sender selectedCell] tag];
    return self;
}

- setXValue_:sender
{
  RtPoint anAxis = { 1.0, 0.0, 0.0 };


  if (yRotateOrTranslate)  // rotate is 0, translate is 1
  {  if (absoluteTransforms)
     {  [shape getTransformMatrix:tmpMatrix];
        tmpMatrix[3][0] = [sender floatValue];
        [shape setTransformMatrix:tmpMatrix];
     }
     else
     {  if (preConcat)
        {  [shape preTranslate:[sender floatValue] :0.0 :0.0];
        }
        else
        {  [shape translate:[sender floatValue] :0.0 :0.0];
        }
     }
  }
  else
  {  if (absoluteTransforms)
     {  [shape getTransformMatrix:tmpMatrix];
        // do some stuff to the matrix here...
        [shape setTransformMatrix:tmpMatrix];
     }
     else
     {  if (preConcat)
        {  [shape preRotateAngle:[sender floatValue] axis:anAxis];
        }
        else
        {  [shape rotateAngle:[sender floatValue] axis:anAxis];
        }
     }
  }
  return self;
}

- setYConstrained_:sender
{
    return self;
}

- setYMax_:sender
{
    return self;
}

- setYMin_:sender
{
    return self;
}

- setYRotateOrTranslate_:sender
{
   yRotateOrTranslate = [[sender selectedCell] tag];
    return self;
}

- setYValue_:sender
{
  RtPoint anAxis = { 0.0, 1.0, 0.0 };


  if (yRotateOrTranslate)  // rotate is 0, translate is 1
  {  if (absoluteTransforms)
     {  [shape getTransformMatrix:tmpMatrix];
        tmpMatrix[3][1] = [sender floatValue];
        [shape setTransformMatrix:tmpMatrix];
     }
     else
     {  if (preConcat)
        {  [shape preTranslate:0.0 :[sender floatValue] :0.0];
        }
        else
        {  [shape translate:0.0 :[sender floatValue] :0.0];
        }
     }
  }
  else
  {  if (absoluteTransforms)
     {  [shape getTransformMatrix:tmpMatrix];
        // do some stuff to the matrix here...
        [shape setTransformMatrix:tmpMatrix];
     }
     else
     {  if (preConcat)
        {  [shape preRotateAngle:[sender floatValue] axis:anAxis];
        }
        else
        {  [shape rotateAngle:[sender floatValue] axis:anAxis];
        }
     }
  }
  return self;
}

- setZConstrained_:sender
{
    return self;
}

- setZMax_:sender
{
    return self;
}

- setZMin_:sender
{
    return self;
}

- setZRotateOrTranslate_:sender
{
   zRotateOrTranslate = [[sender selectedCell] tag];
    return self;
}

- setZValue_:sender
{
  RtPoint  anAxis = { 0.0, 0.0, 1.0 };
  RtFloat  aVal;


  if (yRotateOrTranslate)  // rotate is 0, translate is 1
  {  if (absoluteTransforms)
     {  [shape getTransformMatrix:tmpMatrix];
        tmpMatrix[3][2] = [sender floatValue];
        [shape setTransformMatrix:tmpMatrix];
     }
     else
     {  if ([sender respondsTo:(@selector(relativeFloatValue))])
        {  aVal = [sender relativeFloatValue];
        }
        else
        {  aVal = [sender floatValue];
        }
        if (preConcat)
        {  [shape preTranslate:0.0 :0.0 :aVal];
        }
        else
        {  [shape translate:0.0 :0.0 :aVal];
        }
     }
  }
  else
  {  if (absoluteTransforms)
     {  [shape getTransformMatrix:tmpMatrix];
        // do some stuff to the matrix here...
        [shape setTransformMatrix:tmpMatrix];
     }
     else
     {  if ([sender respondsTo:(@selector(relativeFloatValue))])
        {  aVal = [sender relativeFloatValue];
        }
        else
        {  aVal = [sender floatValue];
        }
        if (preConcat)
        {  [shape preRotateAngle:aVal axis:anAxis];
        }
        else
        {  [shape rotateAngle:aVal axis:anAxis];
        }
     }
  }
  return self;
}


@end
